#ifndef __POINT2__
#define __POINT2__

#include <exception>
#include <functional>

#ifndef byte
typedef unsigned char byte;
#endif

/// <summary>
/// A 2D integer point.
/// </summary>
template<typename T>
struct Point2
{
	/// <summary>
	/// The X component.
	/// </summary>
	T X;

	/// <summary>
	/// The Y component.
	/// </summary>
	T Y;

	Point2() :
		X(0),
		Y(0)
	{
	};

	/// <summary>
	/// Construct a point from raw values.
	/// </summary>
	/// <param name="x">The x parameter.</param>
	/// <param name="y">The y parameter.</param>
	Point2(const T &x, const T &y) :
		X(x),
		Y(y)
	{
	}

	/// <summary>
	/// Construct a point from another point.
	/// </summary>
	/// <param name="p">The point to copy from</param>
	template<typename TA>
	explicit Point2(const Point2<TA> &p) :
		X(p.X),
		Y(p.Y)
	{
	}

	bool operator ==(const Point2 &r) const
	{
		return X == r.X && Y == r.Y;
	}

	bool operator !=(const Point2 &r) const
	{
		return !operator==(r);
	}

	Point2 operator -(const Point2 &r) const
	{
		return Point2(X - r.X, Y - r.Y);
	}
	
	Point2 operator +(const Point2 &r) const
	{
		return Point2(X + r.X, Y + r.Y);
	}

	Point2 &operator +=(const Point2 &r)
	{
		X += r.X;
		Y += r.Y;

		return *this;
	}

	Point2 operator *(const float &r) const
	{
		return Point2(X * r, Y * r);
	}

	Point2 operator /(const float &r) const
	{
		return Point2(X / r, Y / r);
	}

	inline bool operator< (const Point2 &r) const
	{
		return (X < r.X) || ((X == r.X) && (Y < r.Y));
	}

	inline bool operator<= (const Point2 &r) const
	{
		return operator==(r) || operator<(r);
	}

	inline bool operator> (const Point2 &r) const
	{
		return !operator<=(r);
	}

	void Set(const T &x, const T &y)
	{
		X = x;
		Y = y;
	}
};

typedef Point2<int> Point2i;
typedef Point2<float> Point2f;
typedef Point2<byte> Point2b;

#endif